<?php
/**
 * @author		João Batista Neto
 * @brief		Classes e interfaces relacionadas com o protocolo HTTP
 * @package		rpo.http
 */

require_once 'rpo/base/Object.php';

/**
 * @brief		Corpo de uma requisição ou resposta HTTP
 * @class		HTTPBody
 */
class HTTPBody extends Object implements ArrayAccess {
	/**
	 * @brief	Campos do corpo da requisição ou resposta
	 * @var		ArrayObject
	 */
	private $fields;

	/**
	 * @brief	Dados sem tratamento do corpo da requisição ou resposta
	 * @var		string
	 */
	private $data;

	/**
	 * @brief	Constroi o corpo de uma requisição ou resposta HTTP
	 */
	public function __construct(){
		$this->fields = new ArrayObject();
	}

	/**
	 * @brief	Recupera a representação em string do objeto
	 * @return	string
	 */
	public function __toString(){
		return (string) $this->data;;
	}

	/**
	 * @brief	Constroi uma query string com base no conteúdo do corpo
	 * @return	string
	 */
	public function httpBuildQuery(){
		return http_build_query( $this->fields->getArrayCopy() );
	}

	/**
	 * @brief	Verifica se um campo está definido
	 * @param	$offset string Nome do campo
	 * @see		ArrayAccess::offsetExists()
	 */
	public function offsetExists( $offset ){
		return $this->fields->offsetExists( $offset );
	}

	/**
	 * @brief	Recupera o valor de um campo
	 * @param	$offset string Nome do campo
	 * @see		ArrayAccess::offsetGet()
	 * @throws	InvalidArgumentException Se o campo não tiver sido definido
	 */
	public function offsetGet( $offset ){
		if ( $this->offsetExists( $offset ) ){
			return $this->fields->offsetGet( $offset );
		} else {
			throw new InvalidArgumentException( sprintf( 'O offset %s não está definido.' ) );
		}
	}

	/**
	 * @brief	Define o valor de um campo
	 * @param	$offset string Nome do campo
	 * @param	$value mixed Valor do campo
	 * @see		ArrayAccess::offsetSet()
	 * @throws	InvalidArgumentException Se o nome do campo não for uma string
	 */
	public function offsetSet( $offset , $value ){
		if ( is_string( $offset ) ){
			$this->fields->offsetSet( $offset , $value );
		} else {
			throw new InvalidArgumentException( '$offset precisa ser uma string' );
		}
	}

	/**
	 * @brief	Remove a definição de um campo
	 * @param	$offset string Nome do campo
	 * @see		ArrayAccess::offsetUnset()
	 */
	public function offsetUnset( $offset ){
		$this->fields->offsetUnset( $offset );
	}

	/**
	 * @brief	Define o conteúdo do corpo HTTP
	 * @param	$data string
	 */
	public function setData( $data ){
		$this->fields->exchangeArray( array() );
		$this->data = $data;
	}
}